import json
import os
import shutil

class AssemblyPlan:
       
    def __init__(self,filepath):
        self.filepath:str=filepath
        self.root = os.path.dirname(filepath)
        self.info = {}
        self.read_source()
        
    def set_default(self):
        dieinfo = {}
        dieinfo['NumberOfDies']='1'
        dieinfo['DieInfos']=[""]
        self.info = {}
        self.info['FrameInfo'] = ""
        self.info['DieInfo'] = dieinfo
        self.info['BondingTable'] = ""
        self.root = ""
    
    def info_path(self, filepath:str):        
        if ":" not in filepath : # 不包含冒号则认为是相对配置文件的地址
            filepath = os.path.join(self.root, filepath)  
        return filepath   
        
    def check_valid(self):
        res = {'BondingTable'}.issubset(self.info.keys())
        if not res:
            return False
        res = os.path.exists(self.info_path(self.info['BondingTable']))
        if not res:
            return False
        
        res = {'FrameInfo'}.issubset(self.info.keys())
        if not res:
            return False
        res = os.path.exists(self.info_path(self.info['FrameInfo']))
        if not res:
            return False
        
        res = {'DieInfo'}.issubset(self.info.keys())
        if not res:
            return False    
        
        res = {'NumberOfDies'}.issubset(self.info['DieInfo'].keys())
        if not res:
            return False        
        
        try:
            numberOfDies = int(self.info['DieInfo']['NumberOfDies'])
        except ValueError:
            raise ValueError("'NumberOfDies' must be an integer")
        
        if numberOfDies > 0:
            if len(self.info['DieInfo']['DieInfos']) != numberOfDies:
                return False
            
            for filepath in self.info['DieInfo']['DieInfos']:
                res = os.path.exists(self.info_path(filepath))
                if not res:
                    return False
        else:
            return False
        
        return True
        
    def read_source(self):            
        try:
            with open(self.filepath, 'r', encoding='utf-8') as f:
                self.info = json.load(f)
        except FileNotFoundError:
            raise ValueError("Error" f"The file {self.filepath} does not exist.")
        except json.JSONDecodeError:
            raise ValueError("Error" f"The file {self.filepath} is not a valid JSON file.")
        
    def update_source(self):       
        try:
            with open(self.filepath, 'w', encoding='utf-8') as f:
                json.dump(self.info, f, ensure_ascii=False, indent=4)
        except Exception as e:
            raise ValueError(f"Failed to save file: {self.filepath}->{e}")
    
    @staticmethod
    def NewPlan(name):
        try:
             with open(name, 'w') as file:
                file.write('{}') 
        except Exception as e:
            raise ValueError(f"Failed to write file: {e}")
        
        plan =  AssemblyPlan(name)
        plan.set_default()
        plan.update_source()
        return plan
    
    def platforms(self):
        ps = []
        
        ps.append(self.info_path(self.info['FrameInfo']))
        
        for filepath in self.info['DieInfo']['DieInfos']:            
            ps.append(self.info_path(filepath))
        
        return ps

    def bondingtables(self):
        ps = []
        ps.append(self.info_path(self.info['BondingTable']))
        
        return ps
    
